#pragma once
//============================================================================
// Copyright (C) 2008-2013 Brett R. Jones 
// All Rights Reserved
//
// You may redistribute and/or modify for non commercial and commercial uses 
// provided this copyright notice remains in place and is not modified
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

#include <vector>
#include "VxSktThrottle.h"
#include <VxUtilLib/VxMutex.h>
#include "VxSktDefs.h"

class VxSktBase;

// implements a manager to manage multiple sockets
// NOTE: applications should use VxSktAcceptMgr or VxConnnectMgr
class VxSktBaseMgr : public VxSktThrottle
{
public:
	//=== vars ===//
	RCODE						m_rcLastError;
	ESktMgrType					m_eSktMgrType;				// type of sockets we manage
	std::vector<VxSktBase *>	m_aoSkts;					// array of sockets to manage
	std::vector<VxSktBase *>	m_aoSktsToDelete;			// skts that will be deleted after 10 sec 
	VxMutex						m_oSktMgrMutex;				// thread mutex

	VX_SKT_CALLBACK				m_pfnUserRecieve;			// receive function must be set by user
	VX_SKT_CALLBACK				m_pfnOurRecieve;			// our receive function to receive Socket states etc
	VX_SKT_CALLBACK				m_pfnUserTransmit;			// receive function may be set by user
	VX_SKT_CALLBACK				m_pfnOurTransmit;			// our transmit function to get Socket transmit stats

	U32							m_u32MaxConnections;		// max connections we will accept
	UINT						m_uiCreatorThreadId;		// thread id of thread that created this object

	VxInetAddress				m_oLclIp;
	std::string					m_strLclIp;

	//=== constructor ===//
	VxSktBaseMgr();
	//=== destructor ===//
	virtual ~VxSktBaseMgr();

	virtual void sktMgrSetLocalIp( VxInetAddress& oLclIp );

	virtual void sktMgrShutdown( void );

	SOCKET					MakeAndBindTcpSocket( VxInetAddress& oIpAddr, U16 u16Port );

	//! make a new socket... give derived classes a chance to override
	virtual VxSktBase *		makeNewSkt( void );

	//! delete a socket.. allow derived classes to handle differently if they want to
	virtual void			deleteSkt(	VxSktBase *	poSkt );	// skt to remove

	//! close and remove all sockets
	virtual void			ShutdownAllSkts( void );

	void DeleteAllSockets();

	//! User must Set Receive Callback
	virtual void			SetRecieveCallback( VX_SKT_CALLBACK pfnRecieve );
	
	//! Send to all connections
	virtual RCODE			SendToAll(	char * pvData,			// data to send
										int iDataLen );			// length of data

	//! get number of connected sockets
	virtual int				GetConnectedCount( void );
	//! get total number of sockets ( includes not connected sockets )
	virtual int				GetSocketCount( void ){ return (int)m_aoSkts.size(); }

	//! close all sockets
	virtual void			CloseAllSkts( void );

	//=== functions that should only be called by derived classes ===//
	//! handle callbacks from sockets
	virtual	void			DoRecieveCallback( VxSktBase * poSkt );
	//! handle received data ( derived classes must implement )
    virtual	void			HandleRecieveData( VxSktBase * /*poSkt*/ ){};
	//! handle transmit callbacks from sockets
	virtual	void			DoTransmitCallback( VxSktBase * poSkt );
	//! lock access from other threads
	virtual void			DoLock( void );
	//! unlock access from other threads
	virtual void			DoUnlock( void );
	//! add a new socket to manage
	virtual void			AddSkt( VxSktBase * poSkt );
	//! remove a socket from management
	virtual RCODE			RemoveSkt(	VxSktBase *	poSkt,				// skt to remove
										BOOL		bDelete = true );	// if true delete the skt

};

